package com.tentative.competition.schedule.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tentative.competition.common.core.domain.entity.SysUser;
import com.tentative.competition.common.model.schedule.param.*;
import com.tentative.competition.common.utils.SecurityUtils;
import com.tentative.competition.schedule.domain.ScheduleAward;
import com.tentative.competition.schedule.domain.ScheduleScoreDetail;
import com.tentative.competition.schedule.domain.ScheduleWorks;
import com.tentative.competition.schedule.mapper.ScheduleScoreDetailMapper;
import com.tentative.competition.schedule.service.ScheduleAwardService;
import com.tentative.competition.schedule.service.ScheduleScoreDetailService;
import com.tentative.competition.schedule.service.ScheduleWorksService;
import com.tentative.competition.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @auther: Smile Huang
 * @date: 2023/6/27 21:22
 * @desc:
 * @version: 2.0
 */
@Service
public class ScheduleScoreDetailServiceImpl extends ServiceImpl<ScheduleScoreDetailMapper, ScheduleScoreDetail> implements IService<ScheduleScoreDetail>, ScheduleScoreDetailService {

    @Autowired
    private ScheduleWorksService worksService;
    @Autowired
    private ScheduleAwardService awardService;

    @Autowired
    private ISysUserService userService;

    @Override
    public Boolean mark(MarkParam param) {
        //先查询当前作品是否存在过打分，如果存在，需要取平均分设置到作品得分中
        ScheduleWorks works = worksService.lambdaQuery()
                .eq(ScheduleWorks::getId, param.getWorksId())
                .eq(ScheduleWorks::getScheduleId,param.getScheduleId())
                .eq(ScheduleWorks::getDelFlag,0)
                .list()
                .stream()
                .findFirst()
                .orElse(null);
        if (ObjUtil.isEmpty(works)){
            throw new RuntimeException("当前作品不存在！");
        }
        //判断作品是否已经为最终得分，最终得分不在进行打分-此处是做异常抛出，还是不做任何处理
        if (BigDecimal.ROUND_DOWN == works.getFinallyScore()){
            throw new RuntimeException("当前作品评分已截止，最终得分已确认！");
        }
        Long userId = SecurityUtils.getUserId();
        List<ScheduleScoreDetail> scoreDetails = this.lambdaQuery()
                .eq(ScheduleScoreDetail::getWorksId, param.getWorksId())
                .eq(ScheduleScoreDetail::getScheduleId, param.getScheduleId())
                .list();
        ScheduleScoreDetail detail = new ScheduleScoreDetail();
        detail.setScheduleId(param.getScheduleId());
        detail.setScore(param.getScore());
        detail.setComment(param.getComment());
        detail.setUserId(userId);
        detail.setWorksId(param.getWorksId());
        //首次评分-该作品从未评分的情况
        if (CollUtil.isEmpty(scoreDetails)){
            //设置作品得分
            works.setScore(param.getScore());
            worksService.updateById(works);
            return this.save(detail);
        }
        List<ScheduleScoreDetail> scoreDetails1 = scoreDetails.stream().filter(x -> x.getUserId().equals(userId)).collect(Collectors.toList());
        //二次评分
        //当前用户二次评分的情况下，进行评分明细的修改，同样需要修改平均得分
        if (CollUtil.isNotEmpty(scoreDetails1)) {
            ScheduleScoreDetail detail1 = scoreDetails1.get(0);
            detail1.setScore(param.getScore());
            this.updateById(detail1);
        }else {
            //非当前用户首次评分进行新增
            this.save(detail);
        }
        //需要查询修改之后的得分数据
        List<ScheduleScoreDetail> scoreDetailsTow = this.lambdaQuery()
                .eq(ScheduleScoreDetail::getWorksId, param.getWorksId())
                .eq(ScheduleScoreDetail::getScheduleId, param.getScheduleId())
                .list();
        List<String> scoreList = scoreDetailsTow.stream().map(ScheduleScoreDetail::getScore).collect(Collectors.toList());
        //为作品设置平均分
        List<BigDecimal> BigDecimalScore = CollUtil.newArrayList();
        scoreList.forEach(x->BigDecimalScore.add(new BigDecimal(x)));
        BigDecimal average = BigDecimalScore.stream()
                .map(x -> ObjUtil.isEmpty(x) ? new BigDecimal(0) : x)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(BigDecimal.valueOf(BigDecimalScore.size()), 2, BigDecimal.ROUND_HALF_UP);
        works.setScore(average.toString());
        worksService.updateById(works);
        return true;
    }

    @Override
    public Boolean verifyScore(VerifyScoreParam param) {
        ScheduleWorks works = worksService.lambdaQuery()
                .eq(ScheduleWorks::getId, param.getWorksId())
                .eq(ScheduleWorks::getScheduleId,param.getScheduleId())
                .eq(ScheduleWorks::getDelFlag,0)
                .list()
                .stream()
                .findFirst()
                .orElse(null);
        if (ObjUtil.isEmpty(works)){
            throw new RuntimeException("当前作品不存在！");
        }
        works.setFinallyScore(1);
        return worksService.updateById(works);
    }

    @Override
    public Boolean setRating(RatingParam param) {
        ScheduleWorks works = worksService.lambdaQuery()
                .eq(ScheduleWorks::getId, param.getWorksId())
                .eq(ScheduleWorks::getScheduleId,param.getScheduleId())
                .eq(ScheduleWorks::getDelFlag,0)
                .list()
                .stream()
                .findFirst()
                .orElse(null);
        if (ObjUtil.isEmpty(works)){
            throw new RuntimeException("当前作品不存在！");
        }
        ScheduleAward award = awardService.getById(param.getAwardId());
        works.setAwardConfigId(param.getAwardId());
        if(!works.getContent().contains("【所获奖项】")){
            works.setContent("【所获奖项】" + award.getAwardName() + "<br>" + works.getContent());
        }
        return worksService.updateById(works);
    }

    @Override
    public List<ScheduleScoreDetail> getScoreDetail(Long worksId) {
        List<ScheduleScoreDetail> scoreDetails = this.lambdaQuery()
                .eq(ScheduleScoreDetail::getWorksId, worksId)
                .list();
        Set<Long> userIds = scoreDetails.stream().map(ScheduleScoreDetail::getUserId).collect(Collectors.toSet());
        List<SysUser> sysUsers = userService.selectInIds(CollUtil.newArrayList(userIds));
        if (CollUtil.isNotEmpty(sysUsers)){
            Map<Long, SysUser> sysUserMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity()));
            scoreDetails.forEach(x->{
                if (ObjUtil.isNotEmpty(x.getUserId())){
                    x.setUserName(sysUserMap.get(x.getUserId()).getUserName());
                }
            });
        }
        return scoreDetails;
    }

    @Override
    public Boolean editFinallyScore(EditFinallyScoreParam param) {
        ScheduleWorks scheduleWorks = worksService.getById(param.getWorksId());
        //如果作品未确认未最终得分，此时不能进行最终得分修改，否则评委打分会覆盖修改的最终得分
        if (scheduleWorks.getFinallyScore()==BigDecimal.ROUND_DOWN){
            throw new RuntimeException("当前作品处于评委打分阶段，请确认最终得分之后再进行修改！");
        }
        scheduleWorks.setScore(param.getFinallyScore());
        return worksService.saveOrUpdate(scheduleWorks);
    }
}
